//
// Created by luolijun on 2021/10/31.
//

#ifndef MODEL_H
#define MODEL_H

#include "styles.h"

#include <map>
#include <string>

#include <QDebug>

namespace falcon {

struct Facade;
struct Styles;

//! 对象
struct Entity {
    std::string name;
    std::string type;
};

//! 属性
struct Attr : Entity {
    std::string value;
};

//! 属性组
struct AttrGroup : Entity {
    std::map<std::string, Attr> attrs;

    const Attr& operator[](const std::string& attrName) const {
        return attrOf(attrName);
    }

    Attr& operator[](const std::string& attrName) {
        return attrOf(attrName);
    }

    const Attr& attrOf(const std::string& groupType) const {
        const auto itr = attrs.find(groupType);
        if (itr == attrs.end()) {
            Q_ASSERT(false);
        }

        return itr->second;
    }

    Attr& attrOf(const std::string& groupType) {
        const auto itr = attrs.find(groupType);
        if (itr == attrs.end()) {
            Q_ASSERT(false);
        }

        return itr->second;
    }
};

//! 模型
struct Object : public Entity {
    int32_t id;
    Object* parent;
    std::map<std::string, AttrGroup> groups;

    const AttrGroup& operator[](const std::string& groupType) const {
        return groupOf(groupType);
    }

    AttrGroup& operator[](const std::string& groupType) {
        return groupOf(groupType);
    }

    const AttrGroup& groupOf(const std::string& groupType) const {
        const auto itr = groups.find(groupType);
        if (itr == groups.end()) {
            Q_ASSERT(false);
        }

        return itr->second;
    }

    AttrGroup& groupOf(const std::string& groupType) {
        const auto itr = groups.find(groupType);
        if (itr == groups.end()) {
            Q_ASSERT(false);
        }

        return itr->second;
    }
};

struct Package;

//! Diagram 用于记录 Package 中的图元的位置关系
struct Diagram : public Object {
    //! 持有者
    Package* owner;

    //! 该图下持有的装饰对象
    std::vector<Facade*> facades;

    Diagram() {
        type = "diagram";
    }
};

//! Package
struct Package : public Object {
    //! 父包
    Package* parent;

    //! 该包下持有的元素
    std::vector<Object*> objects;

    //! 该包下持有的图
    std::vector<Diagram*> diagrams;

    Package() {
        type = "package";
    }
};

//! Project
struct Project : public Package {
    std::map<std::string, Styles*> styles;

    Project() {
        type = "project";
    }
};

extern int LoadProject(const std::string& fileName, Project* project);
extern int SaveProject(const std::string& fileName, const Project* project);
extern void ClearProject(Package* project);

} // namespace falcon
#endif // MODEL_H
